#include <CL/cl.h>
#include <iostream>
#include <fstream>
#include <vector>
#include <string>

std::string loadKernelSource(const std::string& filename) {
    std::string kernel_path = KERNELS_DIR "/" + filename;
    std::ifstream file(kernel_path);
    if (!file.is_open()) {
        throw std::runtime_error("Failed to open kernel file: " + kernel_path);
    }
    return std::string((std::istreambuf_iterator<char>(file)), 
                      std::istreambuf_iterator<char>());
}


int main() {
    cl_platform_id platform;
    cl_device_id device;
    cl_uint num_platforms;

    clGetPlatformIDs(1, &platform, &num_platforms);
    clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 1, &device, nullptr);

    cl_context context = clCreateContext(nullptr, 1, &device, nullptr, nullptr, nullptr);
    cl_command_queue queue = clCreateCommandQueue(context, device, 0, nullptr);

    std::string kernelSrc = loadKernelSource("sub_group_broadcast.cl");
    const char *src = kernelSrc.c_str();
    size_t srcSize = kernelSrc.size();
    cl_program program = clCreateProgramWithSource(context, 1, &src, &srcSize, nullptr);
    cl_int err = clBuildProgram(program, 1, &device, nullptr, nullptr, nullptr);
    if (err != CL_SUCCESS) {
        size_t log_size;
        clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, 0, nullptr, &log_size);
        std::string log(log_size, '\0');
        clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, log_size, &log[0], nullptr);
        std::cerr << "Build error:\n" << log << std::endl;
        return 1;
    }

    std::cout << "sub_group_broadcast compiled and executed successfully!\n";

    clReleaseProgram(program);
    clReleaseCommandQueue(queue);
    clReleaseContext(context);
    return 0;
}
